/*:
* @plugindesc (v1.04)选择窗口指针跟随鼠标
* @author 小c
* @version 1.0.4
* @date 1/19/2020
*
* @param No Support Windows
* @text 不支持跟随的窗口类
* @type text[]
* @min 1
* @desc 此处用于不需要跟随的窗口
* 比如已经做好了Sprite跟随
*
* @param Auto Move
* @text 光标是否自动移动
* @type boolean
* @on 自动移动
* @off 点击移动
* @desc 当鼠标停留在窗口上下边缘滚动区域时光标的动作。
* 选择点击移动时只有鼠标点击移动区域，光标才会移动。
* @default false
*
* @param Auto Move Wait Count
* @text 自动移动延时
* @type number
* @min 1
* @desc 光标两次自动移动的等待时间
* @default 10
* 
* @help
* 此插件实现选择窗口指针跟随鼠标移动。
* 也可指定一组窗口类，他们不支持跟随。
*
* 修正YEP战斗核心使用单体技能，鼠标悬停在目标上导致键盘移动失效的bug。
* 请将该插件放在YEP战斗核心的下面。
*
* 插件扩展TouchInput内容
* 
* TouchInput.isMoving() 鼠标是否在移动
* TouchInput.realX 和 TouchInput.realY 鼠标实时坐标
*
* 更新日志
* v1.00
* 插件完成
*
* v1.01
* 添加插件参数【光标自动移动】，可自由设置滚动模式
*
* v1.02
* 优化自动移动，只有光标在列表边缘时，鼠标停留在滚动区域才会执行光标上
* 下滚动
* 增加插件参数【自动移动延时】，可自由设置自动移动的速度
*
* v1.03
* 对CP_ExtTitle的适配修改
*
* v1.04
* 修正YEP战斗核心使用单体技能，鼠标悬停在目标上导致键盘移动失效的bug。
*/

var Imported = Imported || {};
Imported.CP_MouseMove = true;

var CP = CP || {};
CP.MouseMoveManager = CP.MouseMoveManager || {};
var params = PluginManager.parameters("CP_MouseMove");

CP.MouseMoveManager.CURSOR_AUTO_MOVE = eval(params["Auto Move"]);
CP.MouseMoveManager.AUTO_MOVE_WAIT_COUNT = Number(params["Auto Move Wait Count"]) || 10;

CP.MouseMoveManager.NO_SUPPORT_WINDOWS = params["No Support Windows"].trim();
if(CP.MouseMoveManager.NO_SUPPORT_WINDOWS != "")
    CP.MouseMoveManager.NO_SUPPORT_WINDOWS = JSON.parse(CP.MouseMoveManager.NO_SUPPORT_WINDOWS);
else
    CP.MouseMoveManager.NO_SUPPORT_WINDOWS = new Array();

for(var i = 0; i < CP.MouseMoveManager.NO_SUPPORT_WINDOWS.length; i++){
    var className = CP.MouseMoveManager.NO_SUPPORT_WINDOWS[i];
    CP.MouseMoveManager.NO_SUPPORT_WINDOWS[i] = "this instanceof " + className;
}

//------------------------------
//         TouchInput
//------------------------------
Object.defineProperty(TouchInput, 'realX', {
    get: function() {
        return this._realX;
    },
    configurable: true
});

Object.defineProperty(TouchInput, 'realY', {
    get: function() {
        return this._realY;
    },
    configurable: true
});

CP.MouseMoveManager.TOUCH_CLEAR = TouchInput.clear;
TouchInput.clear = function() {
    CP.MouseMoveManager.TOUCH_CLEAR.call(this);

    this._oldX = 0;
    this._oldY = 0;
    this._realX = 0;
    this._realY = 0;
    this._moving = false;
};

CP.MouseMoveManager.TOUCH_UPDATE = TouchInput.update;
TouchInput.update = function() {
    CP.MouseMoveManager.TOUCH_UPDATE.call(this);

    this.updateMoving();
    this.updateOld();
};

CP.MouseMoveManager.ON_MOUSE_MOVE = TouchInput._onMouseMove;
TouchInput._onMouseMove = function(event) {
    CP.MouseMoveManager.ON_MOUSE_MOVE.call(this, event);

    var x = Graphics.pageToCanvasX(event.pageX);
    var y = Graphics.pageToCanvasY(event.pageY);

    this.moveRealPosition(x, y);
};

TouchInput.updateOld = function(){
    this._oldX = this._realX;
    this._oldY = this._realY;
};

TouchInput.updateMoving = function(){
    this._moving = this._oldX !== this.realX || this._oldY !== this.realY;
};

TouchInput.moveRealPosition = function(x, y){
    this.updateOld();

	this._realX = x;
	this._realY = y;
};

TouchInput.isMoving = function(){
	return this._moving;
};

//------------------------------
//         Window_Selectable
//------------------------------
Window_Selectable.prototype.processMouseMove = function(){
    if(this.canSupportMove() && this.isOpenAndActive() && this.isMovedInsideFrame()){
       this.onMove();
    }
};

Window_Selectable.prototype.isMovedInsideFrame = function() {
    var x = this.canvasToLocalX(TouchInput.realX);
    var y = this.canvasToLocalY(TouchInput.realY);
    return x >= 0 && y >= 0 && x < this.width && y < this.height;
};

Window_Selectable.prototype.onMove = function() {
    var lastIndex = this.index();
    var x = this.canvasToLocalX(TouchInput.realX);
    var y = this.canvasToLocalY(TouchInput.realY);
    var hitIndex = this.hitTest(x, y);
    if (hitIndex >= 0) {
         if(TouchInput.isMoving() && this.isCursorMovable()) {
            this.select(hitIndex);
        }
    }
    else if(CP.MouseMoveManager.CURSOR_AUTO_MOVE && this._stayCount >= CP.MouseMoveManager.AUTO_MOVE_WAIT_COUNT){
        if (this.isCursorTop() && y < this.padding) {
            this.cursorUp();
        }else if (this.isCursoBottom() && y >= this.height - this.padding) {
            this.cursorDown();
        }
    }
    
    if (this.index() !== lastIndex) {
        SoundManager.playCursor();
    }
};

CP.MouseMoveManager.UPDATE_SELECTABLE = Window_Selectable.prototype.update;
Window_Selectable.prototype.update = function() {
    CP.MouseMoveManager.UPDATE_SELECTABLE.call(this);

    this.processMouseMove();
};

Window_Selectable.prototype.canSupportMove = function(){
    var result = true;
    for(var i = 0; i < CP.MouseMoveManager.NO_SUPPORT_WINDOWS.length; i++){
        try{
            if(eval(CP.MouseMoveManager.NO_SUPPORT_WINDOWS[i]))
                result = false;
        }catch(err){
            result = true;
            console.error(err)
        }
    }

    return result;
};

Window_Selectable.prototype.isCursorTop = function(){
    var index = this.index();
    var minIndex = this.topIndex();
    var maxIndex = minIndex + this.maxCols() - 1;

    if(index >= minIndex && index <= maxIndex)
        return true;

    return false;
};

Window_Selectable.prototype.isCursoBottom = function(){
    var index = this.index();
    var minIndex = this.bottomRow() * this.maxCols();
    var maxIndex = minIndex + this.maxCols() - 1;

    if(index >= minIndex && index <= maxIndex)
        return true;

    return false;
};

if(Imported.YEP_BattleEngineCore){

CP.MouseMoveManager.GET_MOUSE_OVER_ACTOR = Window_BattleActor.prototype.getMouseOverActor;
Window_BattleActor.prototype.getMouseOverActor = function(){
    if(TouchInput.isMoving())
        return CP.MouseMoveManager.GET_MOUSE_OVER_ACTOR.call(this);
    else
        return -1;
};

CP.MouseMoveManager.GET_MOUSE_OVER_ENEMY = Window_BattleEnemy.prototype.getMouseOverEnemy;
Window_BattleEnemy.prototype.getMouseOverEnemy = function(){
    if(TouchInput.isMoving())
        return CP.MouseMoveManager.GET_MOUSE_OVER_ENEMY.call(this);
    else
        return -1;
};

}